package cn.net.xyan.pay.core.support

import org.springframework.beans.factory.config.BeanDefinition
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory
import org.springframework.beans.factory.support.BeanDefinitionBuilder
import org.springframework.beans.factory.support.BeanDefinitionRegistry
import org.springframework.boot.autoconfigure.AutoConfigurationPackages
import org.springframework.context.annotation.Import

import org.springframework.context.annotation.ImportBeanDefinitionRegistrar
import org.springframework.core.io.Resource
import org.springframework.core.io.support.PathMatchingResourcePatternResolver
import org.springframework.core.type.AnnotationMetadata
import java.lang.annotation.*
import java.lang.annotation.Retention
import java.lang.annotation.Target


/**
 * Created by zarra on 2017/5/3.
 */

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(BeanPropertiesPostProcessor::class)
annotation class BeanPropertiesDefinition

class BeanPropertiesPostProcessor: ImportBeanDefinitionRegistrar {

    val filePath:String = "bootstrap.properties"

    override fun registerBeanDefinitions(annotationMetadata: AnnotationMetadata?, registry: BeanDefinitionRegistry?) {

        val resourcePatternResolver = PathMatchingResourcePatternResolver()

        val resources = resourcePatternResolver.getResources(filePath)

        val classNames = resources.flatMap { it.readLines() }

        classNames.forEach {
            val beanDef = beanDefinitionBuilder(Class.forName(it),null,null)

            registry!!.registerBeanDefinition(it,beanDef.beanDefinition)
        }
    }

    fun Resource.readAll():String{
        this.inputStream.use {
            return it.bufferedReader().readText()
        }
    }

    fun Resource.readLines():List<String>{
        this.inputStream.use {
            return it.bufferedReader().readLines()
        }
    }

    fun beanDefinitionBuilder(beanCls: Class<*>, propertyValues: Map<String, Any>?, propertyRefs: Map<String, String>?): BeanDefinitionBuilder {
        val builder = BeanDefinitionBuilder.genericBeanDefinition(beanCls).setLazyInit(false)
        builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE)
        if (propertyValues != null) {
            for (key in propertyValues.keys) {
                builder.addPropertyValue(key, propertyValues[key])
            }
        }
        if (propertyRefs != null) {
            for (key in propertyRefs.keys) {
                builder.addPropertyReference(key, propertyRefs[key])
            }
        }
        return builder
    }


}